package com.example.demo.demos.web.Utils;

import com.example.demo.demos.web.Constants.Constants;
import com.example.demo.demos.web.po.CommonData;
import com.example.demo.demos.web.po.ReportData;
import com.example.demo.demos.web.po.SystemData;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @BelongsProject: demo1
 * @BelongsPackage: com.example.demo.demos.web.Utils
 * @Author: Hu1er
 * @CreateTime: 2023-07-04  16:43
 * @Description: TODO
 * @Version: 1.0
 */


public class Utils {
    public static Map<String, String>  getCommonData(CommonData commonData, SystemData systemData){
        Map<String, String> data = new HashMap<>();
        data.put(Constants.CUSTOMNAME,commonData.getCustomname());
        data.put(Constants.SYSTEMNAME,commonData.getSystemname());
        data.put(Constants.STARTDATE,commonData.getStartdate().toString());
        data.put(Constants.ENDDATE,commonData.getEnddata().toString());
        data.put(Constants.AUDITER,commonData.getAuditer());
        data.put(Constants.MAKER,commonData.getMaker());
        data.put(Constants.SYSTEMURL,systemData.getSystemurl());

        return data;
    }
    /**
     * @Description 创建表格和标题，调用一次创建一个
     * @author Hu1er
     * @version 1.17.0
     * @date 2023/7/5
     */
    public static void createTable(XWPFDocument document, String reportPath) throws IOException, XmlException {

        //获取模板文件样式
        CTStyles styles = document.getStyle();
        //设置新建文档样式为模板中读取到的样式
        XWPFStyles docStyle = document.createStyles();
        docStyle.setStyles(styles);

        // 追加创建标题
        XWPFParagraph title = document.createParagraph();
        //设置标题样式
        title.setStyle("3");
        XWPFRun run = title.createRun();
        //设置标题名称
        run.setText("命令执行漏洞");

        // 追加创建五行两列的表格
        XWPFTable table = document.createTable(5, 2);

        // 设置表格样式
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        CTJc jc = tblPr.addNewJc();
        jc.setVal(STJc.CENTER);

        CTTblWidth tableWidth = tblPr.addNewTblW();
        tableWidth.setType(STTblWidth.DXA);
        tableWidth.setW(BigInteger.valueOf((long) (567 * 14.57)));

        String[] content = new String[]{"风险名称", "风险级别", "风险描述", "测试过程", "加固建议"};
        // 添加数据行
        CTTcPr tcpr = null;
        CTTblWidth cellw = null;
        for (int i = 0; i < 5; i++) {
            XWPFTableRow dataRow = table.getRow(i);
            dataRow.getCell(0).setColor("63B8FF");
            dataRow.getCell(0).setText(content[i]);
            tcpr = dataRow.getCell(0).getCTTc().addNewTcPr();
            cellw = tcpr.addNewTcW();
            cellw.setType(STTblWidth.DXA);
            cellw.setW(BigInteger.valueOf((long) (567 * 2.37)));
        }

        // 保存新生成的 Word 文件
        FileOutputStream fos = new FileOutputStream(reportPath);
        document.write(fos);
        fos.close();

    }

    public static void copyAndReplace(XWPFDocument document, String newPath, Map<String, String> dict) throws Exception {

        FileOutputStream outStream = null;
        try {
            //XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(oldPath));
            List<XWPFParagraph> list = document.getParagraphs();
            //基本内容替换
            replaceInAllParagraphs(list, dict);
            //表格内容替换添加
            replaceInTables(document.getTables(), dict);
            //页眉内容替换添加
            List<XWPFHeader> headerList = document.getHeaderList();
            for (XWPFHeader xwpfHeader : headerList) {
                List<XWPFParagraph> listParagraph = xwpfHeader.getListParagraph();
                replaceInAllParagraphs(listParagraph, dict);
            }
            outStream = new FileOutputStream(newPath);
            document.write(outStream);
            System.out.println(newPath + " 文档生成完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outStream != null) {
                    outStream.flush();
                    outStream.close();
                }
            } catch (IOException ie) {
                ie.printStackTrace();
            }
        }
    }

    //复制样式
    private static void setStyle(XWPFRun oldXWPFRun, XWPFRun newXWPFRun) {
        newXWPFRun.setFontSize(oldXWPFRun.getFontSize());
        newXWPFRun.setFontFamily(oldXWPFRun.getFontFamily());
        newXWPFRun.setBold(oldXWPFRun.isBold());
        newXWPFRun.setColor(oldXWPFRun.getColor());
        newXWPFRun.setUnderline(oldXWPFRun.getUnderline());
    }

    public static void replaceInAllParagraphs(List<XWPFParagraph> xwpfParagraphList, Map<String, String> params) {

        for (XWPFParagraph paragraph : xwpfParagraphList) {
            if (paragraph.getText() == null || paragraph.getText().length() == 0) continue;
            for (String key : params.keySet()) {
                // 对每一段进行多次处理，处理一段中多次出现关键字的情况
                while (paragraph.getText().contains(key)) {
                    replaceInParagraph(paragraph, key, params.get(key));
                }
            }
        }
    }

    /**
     * 替换段落中的字符串
     *
     * @param xwpfParagraph
     * @param oldString
     * @param newString
     */
    public static void replaceInParagraph(XWPFParagraph xwpfParagraph, String oldString, String newString) {
        Map<String, String> pos_map = findSubRunPosInParagraph(xwpfParagraph, oldString);
        int startPoint = Integer.valueOf(pos_map.get("start_pos"));
        int endPoint = Integer.valueOf(pos_map.get("end_pos"));
        if (pos_map != null) {
            List<XWPFRun> runs = xwpfParagraph.getRuns();
            XWPFRun modelRun = runs.get(endPoint);
            XWPFRun xwpfRun = xwpfParagraph.insertNewRun(endPoint + 1);
            String text = pos_map.get("pre_text");
            while (text.contains(oldString)) text = text.replace(oldString, newString);
            xwpfRun.setText(text);
/*            if (modelRun.getFontSize() != -1)
                xwpfRun.setFontSize(modelRun.getFontSize());//默认值是五号字体，但五号字体getFontSize()时，返回-1
            xwpfRun.setFontFamily(modelRun.getFontFamily());*/
            setStyle(modelRun,xwpfRun);
            for (int i = endPoint; i >= startPoint; i--) {
                xwpfParagraph.removeRun(i);
            }
        }
    }


    /**
     * 找到段落中子串的起始XWPFRun下标和终止XWPFRun的下标
     *
     * @param xwpfParagraph
     * @param substring
     * @return
     */
    public static Map<String, String> findSubRunPosInParagraph(XWPFParagraph xwpfParagraph, String substring) {
        List<XWPFRun> runs = xwpfParagraph.getRuns();
        int start_pos = 0;
        int end_pos = 0;
        String subtemp = "";
        for (int i = 0; i < runs.size(); i++) {
            subtemp = "";
            start_pos = i;
            for (int j = i; j < runs.size(); j++) {
                if (runs.get(j).getText(runs.get(j).getTextPosition()) == null) continue;
                subtemp += runs.get(j).getText(runs.get(j).getTextPosition());
                if (subtemp.contains(substring)) {
                    end_pos = j;
                    Map<String, String> map = new HashMap<>();
                    map.put("start_pos", String.valueOf(start_pos));
                    map.put("end_pos", String.valueOf(end_pos));
                    String preText = "";
                    for (int k = start_pos; k <= end_pos; k++) preText += runs.get(k).toString();
                    map.put("pre_text", preText);
                    return map;
                }
            }
        }
        return null;
    }


    /**
     * 替换所有的表格
     *
     * @param xwpfTableList
     * @param params
     */
    public static void replaceInTables(List<XWPFTable> xwpfTableList, Map<String, String> params) {
        for (XWPFTable table : xwpfTableList) {
            replaceInTable(table, params);

        }
    }

    /**
     * 替换一个表格中的所有行
     *
     * @param xwpfTable
     * @param params
     */
    public static void replaceInTable(XWPFTable xwpfTable, Map<String, String> params) {
        List<XWPFTableRow> rows = xwpfTable.getRows();
        replaceInRows(rows, params);
    }


    /**
     * 替换表格中的一行
     *
     * @param rows
     * @param params
     */
    public static void replaceInRows(List<XWPFTableRow> rows, Map<String, String> params) {
        for (int i = 0; i < rows.size(); i++) {
            XWPFTableRow row = rows.get(i);
            replaceInCells(row.getTableCells(), params);
        }
    }

    /**
     * 替换一行中所有的单元格
     *
     * @param xwpfTableCellList
     * @param params
     */
    public static void replaceInCells(List<XWPFTableCell> xwpfTableCellList, Map<String, String> params) {
        for (XWPFTableCell cell : xwpfTableCellList) {
            replaceInCell(cell, params);
        }
    }

    /**
     * 替换表格中每一行中的每一个单元格中的所有段落
     *
     * @param cell
     * @param params
     */
    public static void replaceInCell(XWPFTableCell cell, Map<String, String> params) {
        List<XWPFParagraph> cellParagraphs = cell.getParagraphs();
        replaceInAllParagraphs(cellParagraphs, params);
    }
}
